export function chunk<T>(array: T[], size: number = 1): T[][] {
  const result: T[][] = []
  for (let i = 0; i < array.length; i += size) {
    result.push(array.slice(i, i + size))
  }
  return result
}

/**
 * 基础数组遍历
 * @template T 数组元素类型
 * @param {T[]} array 要遍历的数组
 * @param {(item: T, index: number) => void} callback 对每个元素执行的回调函数
 * @example
 * traverse([1,2,3], (n, i) => console.log(`元素${i}: ${n}`))
 */
export function traverse<T>(array: T[], callback: (item: T, index: number) => void): void {
  array.forEach((item, index) => callback(item, index))
}

/**
 * 多维数组遍历（递归）
 * @template T 数组元素类型
 * @param {T[]} array 要遍历的多维数组
 * @param {(item: T, path: number[]) => void} callback 带路径参数的回调函数
 * @param {keyof T} [childrenField='children'] 子节点字段名
 * @example
 * const data = [{id:1, children:[{id:2}]}]
 * traverseMultiDimensional(data, (item, path) => {
 *   console.log(`路径: ${path.join('.')}`)
 * }, 'children')
 */
export function traverseMultiDimensional<T>(
  array: T[],
  callback: (item: T, path: number[]) => void,
  childrenField: keyof T = 'children' as keyof T,
): void {
  const walk = (arr: T[], path: number[] = []) => {
    arr.forEach((item, index) => {
      callback(item, [...path, index])
      const children = item[childrenField] as unknown as T[]
      if (Array.isArray(children)) {
        walk(children, [...path, index])
      }
    })
  }
  walk(array)
}

/**
 * 树形结构遍历
 * @template T 树节点类型
 * @param {T[]} root 根节点数组
 * @param {(node: T) => void} callback 节点处理回调
 * @param {'DFS'|'BFS'} [mode='DFS'] 遍历模式（深度优先/广度优先）
 * @param {keyof T} [childrenField='children'] 子节点字段名
 * @example
 * const tree = [{value:1, children:[{value:2}]}]
 * traverseTree(tree, node => console.log(node.value), 'DFS')
 */
import { TreeNode } from '../types'

export function traverseTree<T extends TreeNode>(nodes: T[], callback: (node: T) => void, mode: 'DFS' | 'BFS' = 'DFS') {
  if (mode === 'DFS') {
    for (const node of nodes) {
      callback(node);
      if (node.children && Array.isArray(node.children)) {
        traverseTree(node.children as T[], callback, mode);
      }
    }
  } else {
    const queue = [...nodes];
    while (queue.length) {
      const node = queue.shift()!;
      callback(node);
      if (node.children && Array.isArray(node.children)) {
        queue.push(...node.children as T[]);
      }
    }
  }
}

export function compact<T>(array: T[]): T[] {
  return array.filter(Boolean)
}

export function uniq<T>(array: T[]): T[] {
  return Array.from(new Set(array))
}

export function groupBy<T>(array: T[], key: keyof T | ((item: T) => string)): Record<string, T[]> {
  return array.reduce(
    (acc, item) => {
      const groupKey = typeof key === 'function' ? key(item) : String(item[key])
      acc[groupKey] = acc[groupKey] || []
      acc[groupKey].push(item)
      return acc
    },
    {} as Record<string, T[]>,
  )
}
